#include <config.h>
#include <pic_operation.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>


/**********************************************************************
 * 函数名称： PicZoom
 * 功能描述： 近邻取样插值方法缩放图片
 *            注意该函数会分配内存来存放缩放后的图片,用完后要用free函数释放掉
 *            "近邻取样插值"的原理请参考网友"lantianyu520"所著的"图像缩放算法"
 * 输入参数： ptOriginPic - 内含原始图片的象素数据
 *            ptBigPic    - 内含缩放后的图片的象素数据
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
int PicZoom(PT_PixelDatas ptOriginPic, PT_PixelDatas ptZoomPic)
{
    unsigned long dwDstWidth = ptZoomPic->iWidth;
    unsigned long* pdwSrcXTable;
	unsigned long x;
	unsigned long y;
	unsigned long dwSrcY;
	unsigned char *pucDest;
	unsigned char *pucSrc;
	unsigned long dwPixelBytes = ptOriginPic->iBpp/8;

    //DBG_PRINTF("src:\n");
    //DBG_PRINTF("%d x %d, %d bpp, data: 0x%x\n", ptOriginPic->iWidth, ptOriginPic->iHeight, ptOriginPic->iBpp, (unsigned int)ptOriginPic->aucPixelDatas);

    //DBG_PRINTF("dest:\n");
    //DBG_PRINTF("%d x %d, %d bpp, data: 0x%x\n", ptZoomPic->iWidth, ptZoomPic->iHeight, ptZoomPic->iBpp, (unsigned int)ptZoomPic->aucPixelDatas);

	if (ptOriginPic->iBpp != ptZoomPic->iBpp)
	{
		return -1;
	}

    pdwSrcXTable = malloc(sizeof(unsigned long) * dwDstWidth);
    if (NULL == pdwSrcXTable)
    {
        DBG_PRINTF("malloc error!\n");
        return -1;
    }

    for (x = 0; x < dwDstWidth; x++)//生成表 pdwSrcXTable
    {
        pdwSrcXTable[x]=(x*ptOriginPic->iWidth/ptZoomPic->iWidth);
    }

    for (y = 0; y < ptZoomPic->iHeight; y++)
    {			
        dwSrcY = (y * ptOriginPic->iHeight / ptZoomPic->iHeight);

		pucDest = ptZoomPic->aucPixelDatas + y*ptZoomPic->iLineBytes;
		pucSrc  = ptOriginPic->aucPixelDatas + dwSrcY*ptOriginPic->iLineBytes;
		
        for (x = 0; x <dwDstWidth; x++)
        {
            /* 原图座标: pdwSrcXTable[x]，srcy
             * 缩放座标: x, y
			 */
			 memcpy(pucDest+x*dwPixelBytes, pucSrc+pdwSrcXTable[x]*dwPixelBytes, dwPixelBytes);
        }
    }

    free(pdwSrcXTable);
	return 0;
}


/**********************************************************************
 * 函数名称： MyPicZoom
 * 功能描述： 近邻取样插值方法缩放图片
 *            前面的PicZoom是先将缩放的图片放到一个其他的内存
 *            然后再将这个内存的数据复制到显存中
 *            而本程序是直接将缩放的数据放到显存中，省去了中间的步骤
 * 输入参数： ptOriginPic - 内含原始图片的象素数据
 *            ptFrame    - 屏幕的象素数据
 *           iWidth      - 要缩放的宽度
 *           iHeight     - 要缩放的高度
 *            clear_flag - 是否清除无关像素，一般在修改分辨率后使用，避免屏幕出现残影
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2025/04/22	     V1.0	  永远喜欢JK触发器	      创建
 ***********************************************************************/
int MyPicZoom(PT_PixelDatas ptOriginPic, PT_PixelDatas ptFrame, int iWidth, int iHeight,bool clear_flag)
{
    unsigned long dwDstWidth = iWidth;
    unsigned long* pdwSrcXTable;
	unsigned long x;
	unsigned long y;
	unsigned long dwSrcY;
	unsigned char *pucDest;
	unsigned char *pucSrc;
	unsigned long dwPixelBytes = ptOriginPic->iBpp/8;  //当前所使用触摸屏的Bpp为4 * 8 = 32
    int iTopLeftX,iTopLefty;

    unsigned char *pucFrame;
  
    //DBG_PRINTF("src:\n");
    //DBG_PRINTF("%d x %d, %d bpp, data: 0x%x\n", ptOriginPic->iWidth, ptOriginPic->iHeight, ptOriginPic->iBpp, (unsigned int)ptOriginPic->aucPixelDatas);

    //DBG_PRINTF("dest:\n");
    //DBG_PRINTF("%d x %d, %d bpp, data: 0x%x\n", ptZoomPic->iWidth, ptZoomPic->iHeight, ptZoomPic->iBpp, (unsigned int)ptZoomPic->aucPixelDatas);

    if (ptOriginPic->iBpp != ptFrame->iBpp)
	{
		return -1;
	}

	if (iWidth > ptFrame->iWidth || iHeight > ptFrame->iHeight)
	{
		iWidth = ptFrame->iWidth - 1;
        iHeight = ptFrame->iHeight - 1;
	}

    iTopLeftX = (ptFrame->iWidth - iWidth) / 2;
    iTopLefty = (ptFrame->iHeight - iHeight) / 2;

    pdwSrcXTable = malloc(sizeof(unsigned long) * dwDstWidth);
    if (NULL == pdwSrcXTable)
    {
        DBG_PRINTF("malloc error!\n");
        return -1;
    }

    //计算每个目标图像的横坐标x在原图中的对应横坐标
    for (x = 0; x < dwDstWidth; x++)//生成表 pdwSrcXTable
    {
        pdwSrcXTable[x]=(x * ptOriginPic->iWidth / iWidth);
    }

    if(clear_flag)   //仅在视频分辨率变化的时候“清屏”（或者说清除无关区域的像素）
    {
        pucFrame = ptFrame->aucPixelDatas;
        for(y = 0; y < ptFrame->iHeight;y++)
        {
            if(y < iTopLefty || y >= iTopLefty + iHeight)
            {
                memset(pucFrame, 0x00, ptFrame->iLineBytes);  //清除目标图像的行
            }
            else
            {
                memset(pucFrame,0,iTopLeftX * dwPixelBytes);
                memset(pucFrame + (iTopLeftX + iWidth) * dwPixelBytes,0, ptFrame->iLineBytes - (iTopLeftX + iWidth) * dwPixelBytes);  
            }
            pucFrame += ptFrame->iLineBytes;
        }
    }   
    
    pucFrame = ptFrame->aucPixelDatas + iTopLefty * ptFrame->iLineBytes + iTopLeftX * ptFrame->iBpp / 8;  //计算目标图像的起始地址
    for (y = 0; y < iHeight; y++)
    {			
        dwSrcY = (y * ptOriginPic->iHeight / iHeight);   //根据缩放的比例找到原图像对应的行

		pucDest = pucFrame + y * ptFrame->iLineBytes;
		pucSrc  = ptOriginPic->aucPixelDatas + dwSrcY * ptOriginPic->iLineBytes;
		
        for (x = 0; x <dwDstWidth; x++)
        {
            /* 原图座标: pdwSrcXTable[x]，srcy
             * 缩放座标: x, y
			 */
            
            unsigned char *pSrcPixel = pucSrc + pdwSrcXTable[x] * dwPixelBytes;
            unsigned char *pDstPixel = pucDest + x * dwPixelBytes;
            // 由于这里我使用的触摸屏的像素字节为4，故这里直接使用如下方式完成赋值
            pDstPixel[0] = pSrcPixel[0];
            pDstPixel[1] = pSrcPixel[1];
            pDstPixel[2] = pSrcPixel[2];
            pDstPixel[3] = pSrcPixel[3];

            //如果不确定，则可以使用下面的swith来处理
            /*
            switch (dwPixelBytes)
            {
                case 3: // RGB888
                    pDstPixel[0] = pSrcPixel[0];
                    pDstPixel[1] = pSrcPixel[1];
                    pDstPixel[2] = pSrcPixel[2];
                    break;
                case 4: // RGBA8888
                    pDstPixel[0] = pSrcPixel[0];
                    pDstPixel[1] = pSrcPixel[1];
                    pDstPixel[2] = pSrcPixel[2];
                    pDstPixel[3] = pSrcPixel[3];
                    break;
                case 1: // 灰度图
                    pDstPixel[0] = pSrcPixel[0];
                    break;
                default: // 其他像素格式仍然使用 memcpy（作为 fallback）
                    memcpy(pDstPixel, pSrcPixel, dwPixelBytes);
                    break;
            }
            */

			//memcpy(pucDest + x * dwPixelBytes, pucSrc + pdwSrcXTable[x] * dwPixelBytes, dwPixelBytes);   //效率最低~
        }
    }

    free(pdwSrcXTable);
	return 0;
}

